/*
 * hal_iic.c
 *
 *  Created on: Feb 7, 2025
 *      Author: hongwei_zhu
 */

#include "hal_i2c.h"

static uint8_t IIC_ReadOneByte(uint16_t ReadAddr)
{
    uint8_t temp = 0;
    I2C_GenerateSTOP(DISABLE);
    while(I2C_GetFlagStatus(I2C_FLAG_BUSY) != RESET);
    I2C_GenerateSTART(ENABLE);

    while( !I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress((iic.dev_add), I2C_Direction_Transmitter );

    while( !I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) );

    I2C_GenerateSTART(ENABLE );
    while( !I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress( iic.dev_add+1, I2C_Direction_Receiver );

    while( !I2C_CheckEvent( I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) );
    while( I2C_GetFlagStatus( I2C_FLAG_RXNE ) ==  RESET )
    I2C_AcknowledgeConfig( DISABLE );
    temp = I2C_ReceiveData();
    I2C_GenerateSTOP( ENABLE );
    return temp;
}
static void IIC_WriteOneByte(uint16_t WriteAddr, uint8_t DataToWrite)
{
    I2C_GenerateSTOP(DISABLE);
    while(I2C_GetFlagStatus(I2C_FLAG_BUSY) != RESET);
    I2C_GenerateSTART(ENABLE);

    while( !I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress((iic.dev_add), I2C_Direction_Transmitter );

    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    I2C_Send7bitAddress((uint8_t)(WriteAddr & 0x00ff), I2C_Direction_Transmitter);
    while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    if(I2C_GetFlagStatus(I2C_FLAG_TXE) != RESET)
    {
        I2C_Send7bitAddress((uint8_t)(DataToWrite), I2C_Direction_Transmitter);
    }

    while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_GenerateSTOP(ENABLE);
}
static void IIC_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
    uint16_t i;
    I2C_GenerateSTOP(DISABLE);
    while(I2C_GetFlagStatus(I2C_FLAG_BUSY) != RESET);
    I2C_GenerateSTART(ENABLE);

    while( !I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress((iic.dev_add), I2C_Direction_Transmitter );

    while( !I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) );

    I2C_GenerateSTART(ENABLE );
    while( !I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress( iic.dev_add+1, I2C_Direction_Receiver );

    while( !I2C_CheckEvent( I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) );
    for(i = 0; i < NumToRead - 1;i++)
    {
        while( I2C_GetFlagStatus( I2C_FLAG_RXNE ) ==  RESET )
        I2C_AcknowledgeConfig(ENABLE);
        pBuffer[i] = I2C_ReceiveData();
    }

    while( I2C_GetFlagStatus( I2C_FLAG_RXNE ) ==  RESET )
    I2C_AcknowledgeConfig(DISABLE);
    pBuffer[i+1] = I2C_ReceiveData();

    I2C_GenerateSTOP( ENABLE );
}
static void IIC_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
    uint16_t i;
    I2C_GenerateSTOP(DISABLE);
    while(I2C_GetFlagStatus(I2C_FLAG_BUSY) != RESET);
    I2C_GenerateSTART(ENABLE);

    while( !I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT ) );
    I2C_Send7bitAddress((iic.dev_add), I2C_Direction_Transmitter );

    while(!I2C_CheckEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    if(I2C_GetFlagStatus(I2C_FLAG_TXE) != RESET)
    {
        I2C_Send7bitAddress((uint8_t)(WriteAddr & 0x00ff), I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    }
    for(i = 0 ;i < NumToWrite;i++)
    {
        if(I2C_GetFlagStatus(I2C_FLAG_TXE) != RESET)
        {
            I2C_Send7bitAddress(pBuffer[i], I2C_Direction_Transmitter);
        }
        while(!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    }
    I2C_GenerateSTOP(ENABLE);

}
static void IIC_Init(enum IIC_IO_GROUP io_group,uint32_t bound, uint16_t address)
{
    if(io_group == IIC_GROUPB12_13)
    {
        GPIOB_ModeCfg(GPIO_Pin_13 | GPIO_Pin_12, GPIO_ModeIN_PU);
    }
    else if (io_group == IIC_GROUPB20_21) {
        GPIOB_ModeCfg(GPIO_Pin_20 | GPIO_Pin_21, GPIO_ModeIN_PU);
        R16_PIN_ALTERNATE |= RB_PIN_I2C;
    }
    if(iic.dev_add_len == ADDRESS_8bit)
    {
        I2C_Init(I2C_Mode_I2C, bound, I2C_DutyCycle_16_9, I2C_Ack_Enable, I2C_AckAddr_7bit, iic.dev_add);
    }
    else {
        printf("not supported 10bit address!!\r\n");
        while(1);
    }
}

struct iic_type iic ={
        0,
        ADDRESS_8bit,
        IIC_Init,
        IIC_ReadOneByte,
        IIC_WriteOneByte,
        IIC_Read,
        IIC_Write
};
